Türkçe

Metadata yönetimi ve kod modifikasyonu için JavaScript decorator'larının gücünü keşfedin. Uluslararası en iyi uygulamalarla kodunuzu netlik ve verimlilikle nasıl geliştireceğinizi öğrenin.

JavaScript Decorator'ları: Metadata ve Kod Modifikasyonunun Gücünü Ortaya Çıkarın

JavaScript decorator'ları, sınıfların, metotların, özelliklerin ve parametrelerin davranışını değiştirmek ve metadata eklemek için güçlü ve zarif bir yol sunar. Günlükleme (logging), doğrulama (validation), yetkilendirme (authorization) gibi kesişen ilgileri (cross-cutting concerns) koda eklemek için bildirimsel (declarative) bir sözdizimi sağlarlar. Henüz nispeten yeni bir özellik olmalarına rağmen, decorator'lar özellikle TypeScript'te popülerlik kazanmakta ve kod okunabilirliğini, sürdürülebilirliğini ve yeniden kullanılabilirliğini artırmayı vaat etmektedir. Bu makale, dünya çapındaki geliştiriciler için pratik örnekler ve içgörüler sunarak JavaScript decorator'larının yeteneklerini araştırmaktadır.

JavaScript Decorator'ları Nedir?

Decorator'lar aslında diğer fonksiyonları veya sınıfları saran fonksiyonlardır. Dekore edilen öğenin davranışını, orijinal kodunu doğrudan değiştirmeden değiştirme veya geliştirme yolu sunarlar. Decorator'lar sınıfları, metotları, erişimcileri (accessors), özellikleri veya parametreleri dekore etmek için bir fonksiyon adının önünde @ sembolünü kullanır.

Onları, kodunuza kesişen ilgileri uygulamak için daha temiz ve okunabilir bir yol sunan yüksek dereceli fonksiyonlar (higher-order functions) için bir sözdizimsel kolaylık (syntactic sugar) olarak düşünebilirsiniz. Decorator'lar, ilgileri etkili bir şekilde ayırmanıza olanak tanıyarak daha modüler ve sürdürülebilir uygulamalara yol açar.

Decorator Türleri

JavaScript decorator'ları, her biri kodunuzun farklı unsurlarını hedefleyen çeşitli türlerde gelir:

Temel Sözdizimi

Bir decorator uygulama sözdizimi oldukça basittir:

@decoratorName
class MyClass {
  @methodDecorator
  myMethod( @parameterDecorator param: string ) {
    @propertyDecorator
    myProperty: number;
  }
}

İşte bir döküm:

Sınıf Decorator'ları: Sınıf Davranışını Değiştirme

Sınıf decorator'ları, sınıfın kurucusunu (constructor) argüman olarak alan fonksiyonlardır. Şunlar için kullanılabilirler:

Örnek: Sınıf Oluşturmayı Günlükleme

Bir sınıfın yeni bir örneği oluşturulduğunda bunu günlüklemek istediğinizi hayal edin. Bir sınıf decorator'ı bunu başarabilir:

function logClassCreation(constructor: Function) {
  return class extends constructor {
    constructor(...args: any[]) {
      console.log(`${constructor.name} sınıfının yeni bir örneği oluşturuluyor`);
      super(...args);
    }
  };
}

@logClassCreation
class User {
  name: string;

  constructor(name: string) {
    this.name = name;
  }
}

const user = new User("Alice"); // Çıktı: User sınıfının yeni bir örneği oluşturuluyor

Bu örnekte, logClassCreation orijinal User sınıfını, onu genişleten yeni bir sınıfla değiştirir. Yeni sınıfın kurucusu bir mesajı günlükler ve ardından super kullanarak orijinal kurucuyu çağırır.

Metot Decorator'ları: Metot İşlevselliğini Geliştirme

Metot decorator'ları üç argüman alır:

Şunlar için kullanılabilirler:

Örnek: Metot Çağrılarını Günlükleme

Bir metot her çağrıldığında, argümanlarıyla birlikte günlükleyen bir metot decorator'ı oluşturalım:

function logMethodCall(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;

  descriptor.value = function (...args: any[]) {
    console.log(`${propertyKey} metodu şu argümanlarla çağrılıyor: ${JSON.stringify(args)}`);
    const result = originalMethod.apply(this, args);
    console.log(`${propertyKey} metodu şunu döndürdü: ${result}`);
    return result;
  };

  return descriptor;
}

class Calculator {
  @logMethodCall
  add(x: number, y: number): number {
    return x + y;
  }
}

const calculator = new Calculator();
const sum = calculator.add(5, 3); // Çıktı: add metodu şu argümanlarla çağrılıyor: [5,3]
                                 //         add metodu şunu döndürdü: 8

logMethodCall decorator'ı orijinal metodu sarar. Orijinal metodu çalıştırmadan önce, metot adını ve argümanları günlükler. Çalıştırıldıktan sonra ise dönen değeri günlükler.

Erişimci Decorator'ları: Özellik Erişimini Kontrol Etme

Erişimci decorator'ları, metot decorator'larına benzer ancak özellikle getter ve setter metotlarına (erişimcilere) uygulanır. Metot decorator'ları ile aynı üç argümanı alırlar:

Şunlar için kullanılabilirler:

Örnek: Setter Değerlerini Doğrulama

Bir özellik için ayarlanan değeri doğrulayan bir erişimci decorator'ı oluşturalım:

function validateAge(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalSet = descriptor.set;

  descriptor.set = function (value: number) {
    if (value < 0) {
      throw new Error("Yaş negatif olamaz");
    }
    originalSet.call(this, value);
  };

  return descriptor;
}

class Person {
  private _age: number;

  @validateAge
  set age(value: number) {
    this._age = value;
  }

  get age(): number {
    return this._age;
  }
}

const person = new Person();
person.age = 30; // Sorunsuz çalışır

try {
  person.age = -5; // Hata fırlatır: Yaş negatif olamaz
} catch (error:any) {
  console.error(error.message);
}

validateAge decorator'ı, age özelliği için setter'ı yakalar. Değerin negatif olup olmadığını kontrol eder ve eğer negatifse bir hata fırlatır. Aksi takdirde, orijinal setter'ı çağırır.

Özellik Decorator'ları: Özellik Tanımlayıcılarını Değiştirme

Özellik decorator'ları iki argüman alır:

Şunlar için kullanılabilirler:

Örnek: Bir Özelliği Salt Okunur Yapma

Bir özelliği salt okunur yapan bir özellik decorator'ı oluşturalım:

function readOnly(target: any, propertyKey: string) {
  Object.defineProperty(target, propertyKey, {
    writable: false,
  });
}

class Configuration {
  @readOnly
  apiUrl: string = "https://api.example.com";
}

const config = new Configuration();

try {
  (config as any).apiUrl = "https://newapi.example.com"; // Katı modda (strict mode) hata fırlatır
  console.log(config.apiUrl); // Çıktı: https://api.example.com
} catch (error) {
  console.error("'#' nesnesinin salt okunur 'apiUrl' özelliğine atama yapılamaz'", error);
}

readOnly decorator'ı, özellik tanımlayıcısını değiştirmek için Object.defineProperty kullanır ve writable özelliğini false olarak ayarlar. Artık özelliği değiştirmeye çalışmak bir hatayla sonuçlanacak (katı modda) veya yok sayılacaktır.

Parametre Decorator'ları: Parametreler Hakkında Metadata Sağlama

Parametre decorator'ları üç argüman alır:

Parametre decorator'ları diğer türlere göre daha az kullanılır, ancak belirli parametrelerle metadata ilişkilendirmeniz gereken senaryolar için yardımcı olabilirler.

Örnek: Bağımlılık Enjeksiyonu (Dependency Injection)

Parametre decorator'ları, bir metoda enjekte edilmesi gereken bağımlılıkları tanımlamak için bağımlılık enjeksiyonu çatılarında kullanılabilir. Tam bir bağımlılık enjeksiyonu sistemi bu makalenin kapsamı dışında olsa da, işte basitleştirilmiş bir örnek:

const dependencies: any[] = [];

function inject(token: any) {
  return function (target: any, propertyKey: string | symbol, parameterIndex: number) {
    dependencies.push({
      target,
      propertyKey,
      parameterIndex,
      token,
    });
  };
}

class UserService {
  getUser(id: number) {
    return `${id} ID'li kullanıcı`;
  }
}

class UserController {
  private userService: UserService;

  constructor(@inject(UserService) userService: UserService) {
    this.userService = userService;
  }

  getUser(id: number) {
    return this.userService.getUser(id);
  }
}

//Bağımlılıkların basitleştirilmiş olarak alınması
const userServiceInstance = new UserService();
const userController = new UserController(userServiceInstance);
console.log(userController.getUser(123)); // Çıktı: 123 ID'li kullanıcı

Bu örnekte, @inject decorator'ı, userService parametresi hakkındaki metadatayı dependencies dizisinde saklar. Bir bağımlılık enjeksiyonu kabı (container) daha sonra bu metadatayı uygun bağımlılığı çözmek ve enjekte etmek için kullanabilir.

Pratik Uygulamalar ve Kullanım Alanları

Decorator'lar, kod kalitesini ve sürdürülebilirliği artırmak için çok çeşitli senaryolara uygulanabilir:

Decorator Kullanmanın Faydaları

Decorator'lar birkaç önemli fayda sunar:

Dikkat Edilmesi Gerekenler ve En İyi Uygulamalar

Farklı Ortamlarda Decorator'lar

Decorator'lar ESNext spesifikasyonunun bir parçası olsa da, destekleri farklı JavaScript ortamlarında değişiklik gösterir:

Decorator'lara Küresel Bakış Açıları

Decorator'ların benimsenmesi farklı bölgeler ve geliştirici toplulukları arasında değişiklik göstermektedir. TypeScript'in yaygın olarak benimsendiği bazı bölgelerde (örneğin, Kuzey Amerika ve Avrupa'nın bazı bölgeleri), decorator'lar yaygın olarak kullanılmaktadır. JavaScript'in daha yaygın olduğu veya geliştiricilerin daha basit desenleri tercih ettiği diğer bölgelerde, decorator'lar daha az yaygın olabilir.

Ayrıca, belirli decorator desenlerinin kullanımı kültürel tercihlere ve endüstri standartlarına göre değişebilir. Örneğin, bazı kültürlerde daha ayrıntılı ve açık bir kodlama stili tercih edilirken, diğerlerinde daha kısa ve ifade gücü yüksek bir stil tercih edilmektedir.

Uluslararası projelerde çalışırken, bu kültürel ve bölgesel farklılıkları göz önünde bulundurmak ve tüm ekip üyeleri tarafından açık, anlaşılır ve kolayca anlaşılan kodlama standartları oluşturmak önemlidir. Bu, herkesin decorator'ları kullanma konusunda rahat olmasını sağlamak için ek belgeler, eğitim veya mentorluk sağlamayı içerebilir.

Sonuç

JavaScript decorator'ları, kodu metadata ile zenginleştirmek ve davranışı değiştirmek için güçlü bir araçtır. Geliştiriciler, farklı decorator türlerini ve pratik uygulamalarını anlayarak daha temiz, daha sürdürülebilir ve yeniden kullanılabilir kod yazabilirler. Decorator'lar daha geniş çapta benimsendikçe, JavaScript geliştirme dünyasının önemli bir parçası olmaya adaydırlar. Bu güçlü özelliği benimseyin ve kodunuzu yeni zirvelere taşımak için potansiyelini ortaya çıkarın. Her zaman en iyi uygulamaları takip etmeyi ve uygulamalarınızda decorator kullanmanın performans etkilerini göz önünde bulundurmayı unutmayın. Dikkatli planlama ve uygulama ile decorator'lar, JavaScript projelerinizin kalitesini ve sürdürülebilirliğini önemli ölçüde artırabilir. Mutlu kodlamalar!